/*
          _____                   _______                   _____                    _____            ____
         /\    \                 /::\    \                 /\    \                  /\    \          /\   \
        /::\____\               /::::\    \               /::\    \                /::\    \        /::\   \
       /::::|   |              /::::::\    \             /::::\    \              /::::\    \       \:::\   \
      /:::::|   |             /::::::::\    \           /::::::\    \            /::::::\    \       \:::\   \
     /::::::|   |            /:::/--\:::\    \         /:::/\:::\    \          /:::/\:::\    \       \:::\   \
    /:::/|::|   |           /:::/    \:::\    \       /:::/  \:::\    \        /:::/__\:::\    \       \:::\   \
   /:::/ |::|   |          /:::/    / \:::\    \     /:::/    \:::\    \      /::::\   \:::\    \       \:::\   \
  /:::/  |::|___|______   /:::/____/   \:::\____\   /:::/    / \:::\    \    /::::::\   \:::\    \       \:::\   \
 /:::/   |::::::::\    \ |:::|    |     |:::|    | /:::/    /   \:::\ ___\  /:::/\:::\   \:::\    \       \:::\   \
/:::/    |:::::::::\____\|:::|____|     |:::|    |/:::/____/     \:::|    |/:::/__\:::\   \:::\____\       \:::\___\
\::/    / -----/:::/    / \:::\    \   /:::/    / \:::\    \     /:::|____|\:::\   \:::\   \::/    /       /:::/   /
 \/____/      /:::/    /   \:::\    \ /:::/    /   \:::\    \   /:::/    /  \:::\   \:::\   \/____/       /:::/   /
             /:::/    /     \:::\    /:::/    /     \:::\    \ /:::/    /    \:::\   \:::\    \          /:::/   /
            /:::/    /       \:::\__/:::/    /       \:::\    /:::/    /      \:::\   \:::\____\        /:::/   /
           /:::/    /         \::::::::/    /         \:::\  /:::/    /        \:::\   \::/    /       /:::/   /
          /:::/    /           \::::::/    /           \:::\/:::/    /          \:::\   \/____/       /:::/   /
         /:::/    /             \::::/    /             \::::::/    /            \:::\    \          /:::/   /
        /:::/    /               \::/____/               \::::/    /              \:::\____\        /:::/   /
        \::/    /                 --                      \::/____/                \::/    /        \::/   /
         \/____/                                           --                       \/____/          \/___/
*/

/*
 * M7engine is a simple, easy-to-use 2D game engine, currently under heavy construction.
*/

///////TO DO//////////////
//- Entity Animation.
//- Messaging System.
//- Input overhaul. (Unreliable)
//- Room/Level class.
//- Display depth for entities.
//- Simple views abstraction. (Camera/view class)
//- Fullscreen toggle.
//- Sound modifications.
//- Bitmap fonts.
//- Clean up particle system.
//- Timing utils. (?)
//- Lower level graphics. (Bitmaps/backgrounds, etc)
//- Speed Optimizations.
//- Documentation/Comments/Copyright.
//////////////////////////

#ifndef M7ENGINE_H
#define M7ENGINE_H

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <list>
#include <math.h>

#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>

#include "Entity.h"
#include "InputManager.h"
#include "SoundManager.h"
#include "Vector2.h"
#include "Entity.h"
#include "ParticleEmitter.h"
#include "Primitives.h"
#include "Font.h"
#include "CollisionManager.h"
#include "Camera.h"

#define VERSION_MAJOR 0
#define VERSION_MINOR 3

namespace M7engine
{
class Engine
{
private:
    bool fullScreen, redraw;
    int screenWidth, screenHeight, colorDepth, frameRate, frameCount, fps, fpsAccum;
    double fpsTime;
    float scrollX, scrollY;
    std::list<Entity*> entities;
    ALLEGRO_DISPLAY *display;
    ALLEGRO_BITMAP *icon;
    ALLEGRO_EVENT_QUEUE *eventQueue;
    ALLEGRO_TIMER *timer;

public:
    Engine();
    virtual ~Engine();

    bool init(int width, int height, bool fullscreen);
    void close();
    bool update();

    void updateEntities();
    void drawEntities();
    void cleanEntities();
    void addEntity(Entity *entity);
    Entity *findEntity(int id);
    std::list<Entity*> getEntityList() {return entities;}
    long getEntityCount() {return (long)entities.size();}

    void updateCollisions();

    ALLEGRO_DISPLAY* getDisplay() {return display;}
    ALLEGRO_EVENT_QUEUE* getEventQueue() {return eventQueue;}

    void setDrawingTarget(ALLEGRO_BITMAP *arg) {al_set_target_bitmap(arg);}

    int getFrameRate() {return this->frameRate;}
    void setFrameRate(float arg) {this->frameRate = arg; al_set_timer_speed(timer, 1.0/arg);}
    int getFPS() {return this->fps;}
    int getFrameCount() {return this->frameCount;}

    int getScreenWidth() {return this->screenWidth;}
    void setScreenWidth(int value) {this->screenWidth = value;}
    int getScreenHeight() {return this->screenHeight;}
    void setScreenHeight(int value) {this->screenHeight = value;}

    int getColorDepth() {return this->colorDepth;}
    void setColorDepth(int value) {this->colorDepth = value;}

    bool getFullScreen() {return this->fullScreen;}
    void setFullScreen(bool value) {this->fullScreen = value;}

    void setWindowTitle(const char *title) {al_set_window_title(display, title);}

    bool setIcon(const char *filename)
    {icon = al_load_bitmap(filename); if (!icon) {return false;} al_set_display_icon(display, icon); return true;}

    InputManager *inputManager;
    SoundManager *soundManager;
    FontManager *fontManager;
    Primitives *primitives;
    CollisionManager *collisionManager;
    CameraManager *cameraManager;

    InputManager* getInputManager() {return inputManager;}
    SoundManager* getSoundManager() {return soundManager;}
    FontManager* getFontManager() {return fontManager;}
    Primitives* getPrimitives() {return primitives;}
    CollisionManager* getCollisionManager() {return collisionManager;}
};
};

#endif
